// src/utils/request.js
import axios from "axios";
import { ElMessage, ElLoading } from "element-plus";

// 创建Axios实例
const request = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL,
  timeout: 30000,
  headers: {
    "Content-Type": "application/json;charset=utf-8",
  },
});

// Loading实例
let loadingInstance = null;

// 请求拦截器
request.interceptors.request.use(
  (config) => {
    // 添加Token
    const token = localStorage.getItem("accessToken");
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }

    // 显示Loading
    if (config.showLoading !== false) {
      loadingInstance = ElLoading.service({
        lock: false,
        text: "加载中...",
        background: "rgba(0, 0, 0, 0.1)",
      });
    }

    return config;
  },
  (error) => {
    if (loadingInstance) loadingInstance.close();
    ElMessage.error("请求发送失败，请检查网络！");
    return Promise.reject(error);
  }
);

// 响应拦截器 - 自动处理token刷新
request.interceptors.response.use(
  (response) => {
    // 关闭Loading
    if (loadingInstance) loadingInstance.close();

    const { code, data, msg } = response.data;

    // 成功
    if (code === 1 || code === "success") {
      return data;
    }

    // 业务错误
    ElMessage.error(msg || "操作失败，请重试！");
    return Promise.reject(new Error(msg || "业务错误"));
  },
  async (error) => {
    // 关闭Loading
    if (loadingInstance) loadingInstance.close();

    const { config, response } = error;
    
    // token过期处理
    if (response?.status === 401) {
      // 避免刷新token接口也走这个逻辑
      if (config.url?.includes('/auth/refreshToken')) {
        ElMessage.error("登录已过期，请重新登录！");
        handleTokenExpired();
        return Promise.reject(error);
      }

      // 尝试刷新token
      try {
        const newToken = await refreshTokenAndRetry();
        if (newToken) {
          // 重新设置请求头
          config.headers.Authorization = `Bearer ${newToken}`;
          // 重试原请求
          return request(config);
        }
      } catch (refreshError) {
        console.error('Token刷新失败:', refreshError);
        handleTokenExpired();
        return Promise.reject(error);
      }
    }

    // 其他错误处理
    let errorMsg = "请求失败，请稍后重试！";
    if (response) {
      const status = response.status;
      switch (status) {
        case 403:
          errorMsg = "没有权限访问该资源！";
          break;
        case 404:
          errorMsg = "请求地址不存在！";
          break;
        case 500:
          errorMsg = "服务器内部错误，请联系管理员！";
          break;
        default:
          errorMsg = `请求错误（${status}）`;
      }
    } else if (error.request) {
      errorMsg = "网络超时，请检查网络连接！";
    }

    ElMessage.error(errorMsg);
    return Promise.reject(error);
  }
);

/**
 * 刷新token并重试请求
 */
async function refreshTokenAndRetry() {
  // 这里需要动态导入pinia store，避免循环依赖
  const { useUserStore } = await import('@/store/user');
  const userStore = useUserStore();
  
  try {
    return await userStore.refreshToken();
  } catch (error) {
    throw error;
  }
}

/**
 * 处理token过期
 */
function handleTokenExpired() {
  // 清除本地token
  localStorage.removeItem("accessToken");
  localStorage.removeItem("refreshToken");
  localStorage.removeItem("userInfo");
  
  // 跳转到登录页或显示登录模态框
  // 这里可以通过事件总线或其他方式通知应用显示登录框
  window.dispatchEvent(new CustomEvent('token-expired'));
}

// 导出请求方法
export default {
  get(url, params = {}, config = {}) {
    return request({ method: "GET", url, params, ...config });
  },

  post(url, data = {}, config = {}) {
    return request({ method: "POST", url, data, ...config });
  },

  put(url, data = {}, config = {}) {
    return request({ method: "PUT", url, data, ...config });
  },

  delete(url, params = {}, config = {}) {
    return request({ method: "DELETE", url, params, ...config });
  },

  // 上传文件
  upload(url, formData, config = {}) {
    return request({
      method: "POST",
      url,
      data: formData,
      headers: {
        'Content-Type': 'multipart/form-data'
      },
      ...config
    });
  }
};